#include "listbuffer.hpp"

#include "bits.hpp"

namespace buffer
{
	namespace bits
	{
		const byte * Endian::name[] = {"big_endian", "little_endian"};
		Endian::Obj Endian::obj;

		template <>
			void getB(ListBuffer & buffer, char & val)
			{
				buffer.get(&val, 1);
			}

		template <>
			void getB(ListBuffer & buffer, unsigned char & val)
			{
				getB<char>(buffer, (char&)val);
			}

		template <>
			void getB(ListBuffer & buffer, int16_t & val)
			{
				byte ch[2];
				buffer.get(ch, 2);
				val = make_int16(ch[0], ch[1]);
			}

		template <>
			void getB(ListBuffer & buffer, uint16_t & val)
			{
				getB<int16_t>(buffer, (int16_t&)val);
			}

		template <>
			void getB(ListBuffer & buffer, int32_t & val)
			{
				byte ch[4];
				buffer.get(ch, 4);
				val = make_int32(ch[0], ch[1], ch[2], ch[3]);
			}
		
		template <>
			void getB(ListBuffer & buffer, uint32_t & val)
			{
				get<int32_t>(buffer, (int32_t&)val);
			}
		
		template <>
			void getB(ListBuffer & buffer, int64_t & val)
			{
				byte ch[8];
				buffer.get(ch, 8);
				val = make_int64(ch[0], ch[1], ch[2], ch[3],
									ch[4], ch[5], ch[6], ch[7]);
			}
		
		template <>
			void getB(ListBuffer & buffer, uint64_t & val)
			{
				getB<int64_t>(buffer, (int64_t&)val);
			}

		template <>
			void getB(ListBuffer & buffer, std::string & val)
			{
				int32_t len  =  0;
				getB(buffer, len);
				if (len > 0)
				{
					buffer.get(val, len);
				}
				else
				{
					val.clear();
				}
			}

		template <>
			void getL(ListBuffer & buffer, char & val)
			{
				buffer.get(&val, 1);
			}

		template <>
			void getL(ListBuffer & buffer, unsigned char & val)
			{
				buffer.get((byte*)&val, 1);
			}

		template <>
			void getL(ListBuffer & buffer, int16_t & val)
			{
				byte ch[2];
				buffer.get(ch, 2);
				val = make_int16(ch[1], ch[0]);
			}

		template <>
			void getL(ListBuffer & buffer, uint16_t & val)
			{
				getL<int16_t>(buffer, (int16_t&)val);
			}

		template <>
			void getL(ListBuffer & buffer, int32_t & val)
			{
				byte ch[4];
				buffer.get(ch, 4);
				val = make_int32(ch[3], ch[2], ch[1], ch[0]);
			}
		
		template <>
			void getL(ListBuffer & buffer, uint32_t & val)
			{
				getL<int32_t>(buffer, (int32_t&)val);
			}
		
		template <>
			void getL(ListBuffer & buffer, int64_t & val)
			{
				byte ch[8];
				buffer.get(ch, 8);
				val = make_int64(ch[7], ch[6], ch[5], ch[4],
									ch[3], ch[2], ch[1], ch[0]);
			}
		
		template <>
			void getL(ListBuffer & buffer, uint64_t & val)
			{
				getL<int64_t>(buffer, (int64_t&)val);
			}

		template <>
			void getL(ListBuffer & buffer, std::string & val)
			{
				int32_t len  =  0;
				getL(buffer, len);
				if (len > 0)
				{
					buffer.get(val, len);
				}
				else
				{
					val.clear();
				}
			}

		template <>
			void putB(ListBuffer & buffer, const char & val)
			{
				buffer.put(byte0(val));
			}

		template <>
			void putB(ListBuffer & buffer, const unsigned char & val)
			{
				buffer.put(byte0(val));
			}
		
		template <>
			void putB(ListBuffer & buffer, const int8_t & val)
			{
				buffer.put(byte0(val));
			}

		template <>
			void putB(ListBuffer & buffer, const int16_t & val)
			{
				buffer.put(byte1(val));
				buffer.put(byte0(val));
			}
		
		template <>
			void putB(ListBuffer & buffer, const uint16_t & val)
			{
				putB<int16_t>(buffer, (int16_t)val);
			}

		template <>
			void putB(ListBuffer & buffer, const int32_t & val)
			{
				buffer.put(byte3(val));
				buffer.put(byte2(val));
				buffer.put(byte1(val));
				buffer.put(byte0(val));
			}

		template <>
			void putB(ListBuffer & buffer, const uint32_t & val)
			{
				putB<int32_t>(buffer, (int32_t)val);
			}
		
		template <>
			void putB(ListBuffer & buffer, const int64_t & val)
			{
				buffer.put(byte7(val));
				buffer.put(byte6(val));
				buffer.put(byte5(val));
				buffer.put(byte4(val));
				buffer.put(byte3(val));
				buffer.put(byte2(val));
				buffer.put(byte1(val));
				buffer.put(byte0(val));
			}
		
		template <>
			void putB(ListBuffer & buffer, const uint64_t & val)
			{
				putB<int64_t>(buffer, val);
			}
	
		template <>
		void putB(ListBuffer & buffer, const std::string & val)
		{
			int32_t len = val.size();
			putB(buffer, len);
			if (len > 0)
			{
				const char * ptr = val.c_str();
				buffer.put(ptr, ptr + len);
			}
		}

		template <>
			void putL(ListBuffer & buffer, const char & val)
			{
				buffer.put(byte0(val));
			}
		
		template <>
			void putL(ListBuffer & buffer, const unsigned char & val)
			{
				buffer.put(byte0(val));
			}
		
		template <>
			void putL(ListBuffer & buffer, const int8_t & val)
			{
				buffer.put(byte0(val));
			}

		template <>
			void putL(ListBuffer & buffer, const int16_t & val)
			{
				buffer.put(byte0(val));
				buffer.put(byte1(val));
			}

		template <>
			void putL(ListBuffer & buffer, const uint16_t & val)
			{
				putL<int16_t>(buffer, (int16_t)val);
			}
		
		template <>
			void putL(ListBuffer & buffer, const int32_t & val)
			{
				buffer.put(byte0(val));
				buffer.put(byte1(val));
				buffer.put(byte2(val));
				buffer.put(byte3(val));
			}
		
		template <>
			void putL(ListBuffer & buffer, const uint32_t & val)
			{
				putL<int32_t>(buffer, (int32_t)val);
			}
		
		template <>
			void putL(ListBuffer & buffer, const int64_t & val)
			{
				buffer.put(byte0(val));
				buffer.put(byte1(val));
				buffer.put(byte2(val));
				buffer.put(byte3(val));
				buffer.put(byte4(val));
				buffer.put(byte5(val));
				buffer.put(byte6(val));
				buffer.put(byte7(val));
			}
		
		template <>
			void putL(ListBuffer & buffer, const uint64_t & val)
			{
				putL<int64_t>(buffer, (int64_t)val);
			}
		
		template <>
		void putL(ListBuffer & buffer, const std::string & val)
		{
			int32_t len = val.size();
			putL(buffer, len);
			if (len > 0)
			{
				const char * ptr = val.c_str();
				buffer.put(ptr, ptr + len);
			}
		}

	};
};

